/*
 * SPDX-FileCopyrightText: 2022-2024 Andrew Gunnerson
 * SPDX-License-Identifier: GPL-3.0-only
 */

package com.sanji.audio_test

import android.app.NotificationManager
import android.app.Service
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Handler
import android.os.IBinder
import android.os.Looper
import android.util.Log
import androidx.core.content.IntentCompat
import com.sanji.audio_test.output.OutputFile

/**
 * 通知操作服务
 * 处理来自通知的用户操作，如删除文件等
 */
class NotificationActionService : Service() {
    companion object {
        private val TAG = NotificationActionService::class.java.simpleName

        // 删除URI操作的动作标识
        private val ACTION_DELETE_URI = "${NotificationActionService::class.java.canonicalName}.delete_uri"
        // 文件列表额外数据键名
        private const val EXTRA_FILES = "files"
        // 通知ID额外数据键名
        private const val EXTRA_NOTIFICATION_ID = "notification_id"

        /**
         * 创建删除URI的意图
         * @param context 上下文
         * @param files 要删除的输出文件列表
         * @param notificationId 通知ID
         * @return 配置好的意图对象
         */
        fun createDeleteUriIntent(
            context: Context,
            files: List<OutputFile>,
            notificationId: Int,
        ) = Intent(context, NotificationActionService::class.java).apply {
            action = ACTION_DELETE_URI
            // 未使用，但保证与PendingIntents一起使用时filterEquals()的唯一性
            val uniqueSsp = files.asSequence().map { it.uri.toString() }.joinToString("\u0000")
            data = Uri.fromParts("unused", uniqueSsp, null)
            putExtra(EXTRA_FILES, ArrayList(files))
            putExtra(EXTRA_NOTIFICATION_ID, notificationId)
        }
    }

    // 主线程处理器
    private val handler = Handler(Looper.getMainLooper())

    /**
     * 解析删除URI意图
     * @param intent 输入意图
     * @return 包含文件列表和通知ID的Pair对象
     */
    private fun parseDeleteUriIntent(intent: Intent): Pair<List<OutputFile>, Int> {
        // 使用IntentCompat是因为Android 13的一个bug，在release构建中使用新的带class选项的API会导致NullPointerException
        // https://issuetracker.google.com/issues/274185314
        val files = IntentCompat.getParcelableArrayListExtra(
            intent, EXTRA_FILES, OutputFile::class.java)
            ?: throw IllegalArgumentException("未指定文件")

        val notificationId = intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1)
        if (notificationId < 0) {
            throw IllegalArgumentException("无效的通知ID: $notificationId")
        }

        return Pair(files, notificationId)
    }

    /**
     * 绑定服务时返回空的IBinder
     */
    override fun onBind(intent: Intent?): IBinder? = null

    /**
     * 启动服务命令处理
     * @param intent 启动意图
     * @param flags 启动标志
     * @param startId 启动ID
     * @return 服务启动模式
     */
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int =
        try {
            when (intent?.action) {
                ACTION_DELETE_URI -> {
                    val (files, notificationId) = parseDeleteUriIntent(intent)
                    val notificationManager = getSystemService(NotificationManager::class.java)

                    // 在新线程中执行文件删除操作
                    Thread {
                        for (file in files) {
                            val documentFile = file.toDocumentFile(this)

                            Log.d(TAG, "正在删除: ${file.redacted}")
                            try {
                                documentFile.delete()
                            } catch (e: Exception) {
                                Log.w(TAG, "删除失败 ${file.redacted}", e)
                            }
                        }

                        // 在主线程中取消通知并停止服务
                        handler.post {
                            Log.i(TAG, "正在取消通知 $notificationId")
                            notificationManager.cancel(notificationId)
                            stopSelf(startId)
                        }
                    }.start()
                }
                else -> throw IllegalArgumentException("无效的操作: ${intent?.action}")
            }

            START_REDELIVER_INTENT
        } catch (e: Exception) {
            // 创建脱敏的意图用于日志记录
            val redactedIntent = intent?.let { Intent(it) }?.apply {
                setDataAndType(Uri.fromParts("redacted", "", ""), type)
            }

            Log.w(TAG, "处理意图失败: $redactedIntent", e)
            stopSelf(startId)

            START_NOT_STICKY
        }
}